package com.own.component.store.local.method;

import com.own.component.store.core.method.StoreMap;
import com.own.component.store.core.property.LocalStoreProperty;
import com.own.component.store.local.method.scheduler.StoreMapScheduler;
import com.own.component.store.local.method.state.StoreState;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * DefaultLocalStoreMap
 *
 * @author chenxueli
 * @date 2022-06-15 03:14:15
 */
@Slf4j
public class DefaultLocalStoreMap<V> extends DefaultBaseStoreMethod<Map<String, V>> implements StoreMap<V> {

    private final ReentrantReadWriteLock cacheLock = new ReentrantReadWriteLock(true);
    private final Lock writeLock = cacheLock.writeLock();
    private final Lock readLock = cacheLock.readLock();

    public DefaultLocalStoreMap() {
        super(new StoreState<>());
    }

    public DefaultLocalStoreMap(long delay) {
        super(new StoreState<>(), StoreMapScheduler.INSTANCE, delay);
    }

    public DefaultLocalStoreMap(LocalStoreProperty properties) {
        super(new StoreState<>(), StoreMapScheduler.INSTANCE, properties);
    }

    /**
     * 获取缓存的长度
     *
     * @param name 唯一key
     * @return 长度
     */
    @Override
    public Long size(String name) {
        readLock.lock();
        try {
            return (long) getStoreState().get(buildKey(name)).size();
        } finally {
            readLock.unlock();
        }
    }

    /**
     * 获取所有的key
     *
     * @return 所有的key
     */
    @Override
    public Set<String> keySet() {
        readLock.lock();
        try {
            return getStoreState().keySet();
        } finally {
            readLock.unlock();
        }
    }

    /**
     * 获取当前存储的键的map对象
     *
     * @param name 唯一key
     * @return map对象
     */
    @Override
    public Map<String, V> get(String name) {
        readLock.lock();
        try {
            return getStoreState().get(buildKey(name));
        } finally {
            readLock.unlock();
        }
    }

    /**
     * 获取值
     *
     * @param name 唯一key
     * @param key  map key
     * @return 值
     */
    @Override
    public V get(String name, String key) {
        readLock.lock();
        try {
            if (contains(name)) {
                return getStoreState().get(buildKey(name)).get(key);
            } else {
                return null;
            }
        } finally {
            readLock.unlock();
        }
    }

    /**
     * 添加值
     *
     * @param name 唯一key
     * @param map  map对象
     */
    @Override
    public void putAll(String name, Map<String, V> map) {
        writeLock.lock();
        try {
            if (!contains(name)) {
                getStoreState().set(buildKey(name), map);
            } else {
                getStoreState().get(buildKey(name)).putAll(map);
            }
        } finally {
            writeLock.unlock();
        }
    }

    /**
     * 添加值
     *
     * @param name  唯一key
     * @param key   map key
     * @param value 值
     */
    @Override
    public void put(String name, String key, V value) {
        writeLock.lock();
        try {
            if (!contains(name)) {
                getStoreState().set(buildKey(name), new HashMap<>(32));
            }
            getStoreState().get(buildKey(name)).put(key, value);
        } finally {
            writeLock.unlock();
        }
    }

    /**
     * 移除缓存
     *
     * @param name 唯一key
     * @param key  map key
     */
    @Override
    public void remove(String name, String key) {
        writeLock.lock();
        try {
            if (contains(name)) {
                getStoreState().get(buildKey(name)).remove(key);
            }
        } finally {
            writeLock.unlock();
        }
    }

    /**
     * 是否存啊在
     *
     * @param name 唯一key
     * @param key  map key
     * @return 是否存在
     */
    @Override
    public boolean contains(String name, String key) {
        readLock.lock();
        try {
            if (contains(name)) {
                return getStoreState().get(buildKey(name)).containsKey(key);
            }
            return false;
        } finally {
            readLock.unlock();
        }
    }

    /**
     * 获取缓存的长度
     *
     * @param name 唯一key
     * @param key  map key
     * @return 长度
     */
    @Override
    public Long size(String name, String key) {
        readLock.lock();
        try {
            if (contains(name)) {
                return (long) getStoreState().get(buildKey(name)).size();
            }
            return null;
        } finally {
            readLock.unlock();
        }
    }

    /**
     * 获取所有的键set
     *
     * @param name 唯一key
     * @return set
     */
    @Override
    public Set<String> keySet(String name) {
        readLock.lock();
        try {
            if (contains(name)) {
                return getStoreState().get(buildKey(name)).keySet();
            }
            return new HashSet<>();
        } finally {
            readLock.unlock();
        }
    }

    /**
     * 获取所有的值set
     *
     * @param name 唯一key
     * @return 值列表
     */
    @Override
    public Collection<V> values(String name) {
        readLock.lock();
        try {
            if (contains(name)) {
                return getStoreState().get(buildKey(name)).values();
            }
            return new ArrayList<>();
        } finally {
            readLock.unlock();
        }
    }

}
